package cloud.demarcia.rabbitregister.service.impl;

import cloud.demarcia.rabbitregister.entity.MemberEntity;
import cloud.demarcia.rabbitregister.enums.LoginStatusCode;
import cloud.demarcia.rabbitregister.exception.RabbitLoginException;
import cloud.demarcia.rabbitregister.repository.MemberRepository;
import cloud.demarcia.rabbitregister.service.LoginService;
import cloud.demarcia.rabbitregister.util.PasswordEncipher;
import cloud.demarcia.rabbitregister.vo.UserLoginVo;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.IdUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.signers.JWTSigner;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * @author Bojun Wen, wen_bj@outlook.com
 * @date 2022.02.19
 */
@Service
public class LoginServiceImpl implements LoginService {

    @Resource
    private JWTSigner signer;
    @Resource
    private PasswordEncipher passwordEncipher;

    @Resource
    private MemberRepository memberRepository;

    @Override
    public String getToken(UserLoginVo loginVo) {

        if (Validator.isEmail(loginVo.getUsername())) {
            MemberEntity entity = memberRepository.findByEmail(loginVo.getUsername());
            if (unMatchPassword(loginVo.getPassword(), entity.getPassword())) {
                throw new RabbitLoginException(LoginStatusCode.PASSWORD_ERROR);
            }
            return generateJwt(entity.getUsername(), entity.getId());
        }
        if (Validator.isMatchRegex("^[a-z0-9]{6,12}$", loginVo.getUsername())) {
            MemberEntity entity = memberRepository.findByUsername(loginVo.getUsername());
            if (unMatchPassword(loginVo.getPassword(), entity.getPassword())) {
                throw new RabbitLoginException(LoginStatusCode.PASSWORD_ERROR);
            }
            return generateJwt(entity.getUsername(), entity.getId());
        }
        throw new RabbitLoginException(LoginStatusCode.INPUT_INVALID);
    }

    private boolean unMatchPassword(String raw, String encoded) {
        String decoded = passwordEncipher.decode(encoded);
        return !decoded.equals(raw);
    }

    private String generateJwt(String name, int uid) {
        return JWT.create()
                .setIssuedAt(DateUtil.date())
                .setExpiresAt(DateUtil.tomorrow())
                .setIssuer("rabbit_auth_server")
                .setJWTId(IdUtil.getSnowflake().nextIdStr())
                .setSubject("rabbit_general")
                .setPayload("aud", name)
                .setPayload("uid", uid)
                .setSigner(signer)
                .sign();
    }
}
